package com.right.controller;

import com.right.NettyConfig;
import com.right.command.CsCommand;
import com.right.common.ResponseData;
import com.right.factory.NodeStatus;
import com.right.factory.PackageFactory;
import com.right.handler.*;
import com.right.mapper.*;
import com.right.netty.server.Server;
import io.netty.channel.Channel;
import io.netty.handler.logging.LogLevel;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

import javax.annotation.PostConstruct;
import java.util.Enumeration;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

/**
 * <pre>
 *     @author : pillar
 *     e-mail : 347637454@qq.com
 *     time   : 2018/12/19 15:08
 *     desc   :
 *     version: 1.0
 * </pre>
 */
@RestController
@RequestMapping("test")
@Api(description = "测试")
public class TestController {
    @Autowired
    private NettyConfig nettyConfig;

    @Autowired
    private BicycleTemporarinessMapper bicycleTemporarinessMapper;

    @Autowired
    private BicycleMapper bicycleMapper;

    @Autowired
    private BicycleLockMapper bicycleLockMapper;

    @Autowired
    private BicycleTraceMapper bicycleTraceMapper;

    @Autowired
    private BicycleLocationMapper bicycleLocationMapper;

    private  ControlHandler controlHandler;
    @Autowired
    private BicycleDockSiteMapper bicycleDockSiteMapper;
    @Autowired
    private CommonMapper commonMapper;
    @Autowired
    private  UnlockMapper unlockMapper;

    @PostConstruct
    private void start() {
        Server server = new Server(nettyConfig.getPort(), PackageFactory.createDefault());
        server.getConfiguration().setLogLevel(LogLevel.DEBUG);
        server.init();
        server.addHandler(new LoginHandler(bicycleTemporarinessMapper,
                        bicycleMapper, bicycleLockMapper),
                        new LocationHandler(bicycleTemporarinessMapper, bicycleMapper,
                        bicycleTraceMapper, bicycleLocationMapper),
                        new LockHandler(bicycleMapper,bicycleDockSiteMapper,commonMapper),
                        controlHandler = new ControlHandler(),
                        new AppUnlockHandler(),
                        new UnLockHandler(),
                        new InSiteHandler(),
                        new LockStatusHandler(),
                        new SetAudioHandler(),
                        new SetGpsHandler(),
                        new SetIpHandler(),
                        new ShakeHandler(),
                        new NormalCardUnlockHandler(unlockMapper,bicycleMapper,commonMapper),
                        new BankCardUnlockHandler(unlockMapper,bicycleMapper,commonMapper),
                        new HeartHandler(bicycleLockMapper));
        try {
            if (server.isStarted()){
                return;
            }
            server.start();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    @ApiIgnore
    @GetMapping("send/sample")
    @ApiOperation("发送指令模板")
    public void sed(@ApiParam(required = true,value = "设备编号")@RequestParam("lockNo")String lockNo) throws InterruptedException {
        Channel channel = NodeStatus.getInstance().getClientByImei(lockNo);
        if (channel == null){
            return;
        }
        channel.writeAndFlush("组包指令");
        CountDownLatch c = new CountDownLatch(1);
        controlHandler.setLock(c);
        c.await(10, TimeUnit.SECONDS);
        /*获取接收到的数据,返回给前端*/
        List<String> dataList = controlHandler.getDataList();
    }

    @GetMapping("unlocking")
    @ApiOperation("App开锁指令 301")
    public ResponseData unlocking(@ApiParam(required = true,value = "设备编号")@RequestParam("lockNo")String lockNo) throws InterruptedException {
        Channel channel = NodeStatus.getInstance().getClientByImei(lockNo);
        if (channel == null){
            return new ResponseData(-1,"锁离线");
        }
        String content = CsCommand.APP_UNLOCK;

        channel.writeAndFlush(content);
        CountDownLatch c = new CountDownLatch(1);
        controlHandler.setCurrentCmd(CsCommand.APP_UNLOCK);
        controlHandler.setLock(c);
        c.await(10, TimeUnit.SECONDS);
        /*获取接收到的数据,返回给前端*/
        List<String> dataList = controlHandler.getDataList();
        return new ResponseData(dataList);
    }

    @GetMapping("status")
    @ApiOperation("获取锁状态")
    public ResponseData getLockStatus(@ApiParam(required = true,value = "设备编号")@RequestParam("lockNo")String lockNo) throws InterruptedException {

        Channel channel = NodeStatus.getInstance().getClientByImei(lockNo);
        if (channel == null){
            return new ResponseData(-1,"锁离线");
        }
        String content = CsCommand.LOCK_STATE;

        channel.writeAndFlush(content);
        CountDownLatch c = new CountDownLatch(1);
        controlHandler.setLock(c);
        c.await(10, TimeUnit.SECONDS);
        /*获取接收到的数据,返回给前端*/
        List<String> dataList = controlHandler.getDataList();
        return new ResponseData(dataList);
    }

    @GetMapping("setIp")
    @ApiOperation("更改服务器地址")
    public ResponseData setIp(@ApiParam(required = true,value = "设备编号")@RequestParam("lockNo")String lockNo,
                              @ApiParam(required = true,value = "ip地址")@RequestParam("server")String server,
                              @ApiParam(required = true,value = "端口号")@RequestParam("port")String port) throws InterruptedException {

        Channel channel = NodeStatus.getInstance().getClientByImei(lockNo);
        if (channel == null){
            return new ResponseData(-1,"锁离线");
        }
        String content = CsCommand.SET_IP + "," + server + "," + port;

        channel.writeAndFlush(content);
        CountDownLatch c = new CountDownLatch(1);
        controlHandler.setLock(c);
        c.await(10, TimeUnit.SECONDS);
        /*获取接收到的数据,返回给前端*/
        List<String> dataList = controlHandler.getDataList();
        return new ResponseData(dataList);
    }

    @GetMapping("update/shake")
    @ApiOperation("更改震动设备")
    public ResponseData updateShake(@ApiParam(required = true,value = "设备编号")@RequestParam("lockNo")String lockNo,
                                    @ApiParam(required = true,value = "震动状态 0 关闭震动检测，1 开启震动检测")@RequestParam("status")int status
                                   ) throws InterruptedException {
        Channel channel = NodeStatus.getInstance().getClientByImei(lockNo);
        if (channel == null){
            return new ResponseData(-1,"锁离线");
        }
        String content = CsCommand.SET_SHAKE+","+status;

        channel.writeAndFlush(content);
        CountDownLatch c = new CountDownLatch(1);
        controlHandler.setLock(c);
        c.await(10, TimeUnit.SECONDS);
        /*获取接收到的数据,返回给前端*/
        List<String> dataList = controlHandler.getDataList();
        return new ResponseData(Objects.equals("1",dataList.get(1))?"成功":"失败");
    }


    @GetMapping("set/arearLock")
    @ApiOperation("设置是否是区域锁")
    public ResponseData setArearLock(@ApiParam(required = true,value = "设备编号")@RequestParam("lockNo")String lockNo,
                                     @ApiParam(required = true,value = "是否区域锁，0 普通锁，1 区域锁")@RequestParam("status")int status
                                   ) throws InterruptedException {
        Channel channel = NodeStatus.getInstance().getClientByImei(lockNo);
        if (channel == null){
            return new ResponseData(-1,"锁离线");
        }

        String content = CsCommand.SET_AREAR_LOCK+","+status;

        channel.writeAndFlush(content);
        CountDownLatch c = new CountDownLatch(1);
        controlHandler.setLock(c);
        c.await(10, TimeUnit.SECONDS);
        /*获取接收到的数据,返回给前端*/
        List<String> dataList = controlHandler.getDataList();
        return new ResponseData(Objects.equals("1",dataList.get(1))?"成功":"失败");
    }

    @GetMapping("set/audio")
    @ApiOperation("设置进出区域状态及铃声205")
    public ResponseData setAudio(
            @ApiParam(required = true,value = "设备编号")@RequestParam("lockNo")String lockNo,
            @ApiParam(required = true,value = "OverTime 0 不可锁车，1 可以锁车，>1 可以锁车超时时间")@RequestParam("OverTime")String OverTime,
            @ApiParam(required = true,value = "BeepCount")@RequestParam("BeepCount")String BeepCount
                                   ) throws InterruptedException {
        Channel channel = NodeStatus.getInstance().getClientByImei(lockNo);
        if (channel == null){
            return new ResponseData(-1,"锁离线");
        }
        String content = CsCommand.SET_AUDIO+","+OverTime +","+BeepCount;

        channel.writeAndFlush(content);
        CountDownLatch c = new CountDownLatch(1);
        controlHandler.setCurrentCmd(CsCommand.SET_AUDIO);
        controlHandler.setLock(c);
        c.await(10, TimeUnit.SECONDS);
        /*获取接收到的数据,返回给前端*/
        List<String> dataList = controlHandler.getDataList();
        return new ResponseData(dataList);
    }

    @GetMapping("set/gps")
    @ApiOperation("更改 GPS 回报时间间隔指令")
    public ResponseData setGps(
            @ApiParam(required = true,value = "设备编号")@RequestParam("lockNo")String lockNo,
            @ApiParam(required = true,value = "锁车回报时间间隔（秒） ，0 为停止回报，小于 5 秒时自动\n" +
                    "更正为 5 秒")@RequestParam("LockSecond")String LockSecond ,
            @ApiParam(required = true,value = "开锁状态回报时间间隔，同 LockSecond")@RequestParam("RunSecond")String RunSecond
            ) throws InterruptedException {
        Channel channel = NodeStatus.getInstance().getClientByImei(lockNo);
        if (channel == null){
            return new ResponseData(-1,"锁离线");
        }
        String content = CsCommand.SET_GPS+","+LockSecond +","+RunSecond;

        channel.writeAndFlush(content);
        CountDownLatch c = new CountDownLatch(1);
        controlHandler.setLock(c);
        c.await(10, TimeUnit.SECONDS);
        /*获取接收到的数据,返回给前端*/
        List<String> dataList = controlHandler.getDataList();
        return new ResponseData(dataList);
    }


    @GetMapping("lock/list")
    @ApiOperation("获取在线锁列表")
    public ResponseData getAllOnlineLock(){
        Enumeration<String> list = NodeStatus.getInstance().getAllLockNo();
        return new ResponseData(list);
    }

}
